package com.invernadero.invernaderotesis.Servicios.ServiciosWeb.Rest;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.invernadero.invernaderotesis.Modelo.Enumerados.RequestMethod;
import com.invernadero.invernaderotesis.Servicios.Services.Servicio;


public class RestClient extends Servicio
{

	/**
	 * Atributos
	 */
    private ArrayList <NameValuePair> params;
    private ArrayList <NameValuePair> headers;
    private JSONArray jArrayParam;
    private JSONObject jsonObject;
    private String strJson = "";
    private String respStr = "";
    
    /**
     * Constructores
     * @param url
     */
    public RestClient()
    {
    	super();
    }
    
    public RestClient(String url)
    {
    	//super();
        this.setUrl(url);
        
      // instanciamos un ArrayList para "params" y "headers"
        params = new ArrayList<NameValuePair>();
        headers = new ArrayList<NameValuePair>();
        jArrayParam = new JSONArray();
        jsonObject = new JSONObject();
    }

    /**
     * Getters & Setters
     * @return
     */
    public String getRespStr() {
		return respStr;
	}

	public void setRespStr(String respStr) {
		this.respStr = respStr;
	}
	
    public String getStrJson() {
		return strJson;
	}

	public void setStrJson(String strJson) {
		this.strJson = strJson;
	}

	public Boolean getRespuesta()
    {
    	Boolean result = false;
    	JSONArray respJSON = new JSONArray();
    	
    	try {
    		
    		JSONObject jo = new JSONObject(this.getResponse());
    		
			//respJSON = new JSONArray(this.getResponse());
			
			if (jo.length() > 0)
			{
				//JSONObject obj = respJSON.getJSONObject(0);
				result = jo.getBoolean("Resultado");				
			} // if
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
    	return result;
    	
    			
    } // getRespuesta
    
    public String getMensageErrorRespuesta()
    {
    	String result = "";
    	JSONArray respJSON = new JSONArray();
    	
    	try {
    		
    		JSONObject jo = new JSONObject(this.getResponse());
    		
			//respJSON = new JSONArray(this.getResponse());
			
			if (jo.length() > 0)
			{
				//JSONObject obj = respJSON.getJSONObject(0);
				result = jo.getString("Error");				
			} // if
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
    	return result;
    	
    } // getMensageErrorRespuesta
    
    public Integer getIdRespuesta()
    {
    	Integer result = 0;
    	JSONArray respJSON = new JSONArray();
    	
    	try {
    		
    		JSONObject jo = new JSONObject(this.getResponse());
    		
			//respJSON = new JSONArray(this.getResponse());
			
			if (jo.length() > 0)
			{
				//JSONObject obj = respJSON.getJSONObject(0);
				result = jo.getInt("Id");				
			} // if
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
    	return result;
    } // getIdRespuesta
    
    /***
     * Obtiene la respuesta del Id generado en el sistema de 3G,
     * Este siempre vendra en un campo llamado "Id"
     * @return
     */
    public int getIdGenerado()
    {
    	int result = 0;
    	JSONArray respJSON = new JSONArray();
    	
    	try {
    		
    		JSONObject jo = new JSONObject(this.getResponse());
    		
			//respJSON = new JSONArray(this.getResponse());
			
			if (jo.length() > 0)
			{
				//JSONObject obj = respJSON.getJSONObject(0);
				result = jo.getInt("Id");				
			} // if
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
    	return result;
    } // getIdGenerado
    

    public JSONArray getjArrayParam() {
		return jArrayParam;
	}

	public void addJSONArray (JSONObject objeto)
    {
    	jArrayParam.put(objeto);
    }
    
    
    public JSONObject getJsonObject() {
		return jsonObject;
	}

	public void addjsonObject(String campo, boolean valor)
    {
    	try {
			jsonObject.put(campo, valor);
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    public void addjsonObject(String campo, double valor)
    {
    	try {
			jsonObject.put(campo, valor);
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    public void addjsonObject(String campo, int valor)
    {
    	try {
			jsonObject.put(campo, valor);
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    public void addjsonObject(String campo, long valor)
    {
    	try {
			jsonObject.put(campo, valor);
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    public void addjsonObject(String campo, Object valor)
    {
    	try {
			jsonObject.put(campo, valor);
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    

    public void AddParam(String name, String value)
    {
        params.add(new BasicNameValuePair(name, value));
    }
    
    public void AddJsonParam(String nombre)
    {
        params.add(new BasicNameValuePair(nombre, this.getjArrayParam().toString()));
    }

    public void AddHeader(String name, String value)
    {
        headers.add(new BasicNameValuePair(name, value));
    } // AddHeader

    /**
     * Armamos el Request con el DOM pasando por parametros si va ser
     * una llamada del tipo "GET" o "POST"
     * 
     * @param method
     * @throws Exception
     */
    public void Execute(RequestMethod method) throws Exception
    {
        switch(method) {
            case GET:
            {
                //add parameters
                String combinedParams = "";
                if(!params.isEmpty()){
                    combinedParams += "?";
                    for(NameValuePair p : params)
                    {
                        String paramString = p.getName() + "=" + URLEncoder.encode(p.getValue(), HTTP.UTF_8);
                        if(combinedParams.length() > 1)
                        {
                            combinedParams  +=  "&" + paramString;
                        }
                        else
                        {
                            combinedParams += paramString;
                        }
                    }
                }

                HttpGet request = new HttpGet(this.getUrl() + combinedParams);
             // 3. Indica que el tipo de operacion sera JSON
                request.setHeader("content-type", "application/json");
                
                //add headers
                for(NameValuePair h : headers)
                {
                    request.addHeader(h.getName(), h.getValue());
                }

                executeRequest(request, this.getUrl());
                break;
            }
            case POST:
            {
                HttpPost request = new HttpPost(this.getUrl());

//                request.setHeader("content-type", "application/json");
//                request.setHeader("Accept", "application/json");
                
                //add headers
                for(NameValuePair h : headers)
                {
                    request.addHeader(h.getName(), h.getValue());
                }

                if(!params.isEmpty()){
                	
                	try {
						//HttpEntity entity = new UrlEncodedFormEntity(params, HTTP.UTF_8);
                		StringEntity entity = null;

                		if (this.strJson.trim().length() > 0)
                			entity = new StringEntity(this.getStrJson());
                		else
                			entity = new StringEntity(this.getJsonObject().toString());
                			
                		entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
                		
						request.setEntity(entity);
						
						request.setHeader("content-type", "application/json"); 
                        request.setHeader("Accept", "application/json");
                        request.setHeader("encoding", "ISO-8859-1");
                        request.setHeader("charset", "UTF-8");
                        
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
                	
                	
//                    request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
                }

                executeRequest(request, this.getUrl());
                break;
            }
        }
    } // Execute

    /**
     * Ejecutamos el "Request" del servicio invocando al servicio Rest
     * 
     * @param request
     * @param url
     */
    private void executeRequest(HttpUriRequest request, String url)
    {
        HttpClient client = new DefaultHttpClient();

        HttpResponse httpResponse;

        try {
            httpResponse = client.execute(request);
            this.setResponseCode(httpResponse.getStatusLine().getStatusCode());
            this.setMessage(httpResponse.getStatusLine().getReasonPhrase());

            HttpEntity entity = httpResponse.getEntity();

            if (entity != null) {

            	// Captura el resultado REST en una cadena string para asi manipularlo
    			setRespStr(EntityUtils.toString(entity));
    			
                InputStream instream = entity.getContent();
                response = convertStreamToString(instream);

                // Closing the input stream will trigger connection release
                instream.close();
                
            	
            }

        } catch (ClientProtocolException e)  {
            client.getConnectionManager().shutdown();
            e.printStackTrace();
        } catch (IOException e) {
            client.getConnectionManager().shutdown();
            e.printStackTrace();
        }
        
    } // executeRequest

    /**
     * Metodo para convertir el "InputStream" a "String
     * @param is
     * @return
     */
    private static String convertStreamToString(InputStream is)
    {

        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    } // convertStreamToString
    
} // clase
